import { GM_registerMenuCommand } from "tm";
import caches from "./apis/caches.mjs";
import cookies from "./apis/cookies.mjs";
import stors from "./apis/stors.mjs";
import dbs from "./apis/indexedDBs.mjs";
import { gmHostMenu, isEmotionUsed } from "./utilities.mjs";
import { initUI } from "./ui/init";
import { DataString, DataType, hint } from "./data.mts";

async function runner(
  bit: number,
  type: number,
  caller: () => Promise<void>,
  emsg: string,
) {
  if ((type & bit) === bit) {
    try {
      await caller();
    } catch (error) {
      console.error(emsg, error);
    }
  }
}

async function getData(type: number) {
  const data: {
    cache?: Awaited<ReturnType<typeof caches.query>>;
    cookie?: Awaited<ReturnType<typeof cookies.query>>;
    lstor?: Awaited<ReturnType<typeof stors.query>>;
    sstor?: Awaited<ReturnType<typeof stors.query>>;
    dbs?: Awaited<ReturnType<typeof dbs.query>>;
  } = {};

  const getter = {
    indexedDB: async () => {
      data.dbs = await dbs.query();
    },
    sStor: async () => {
      data.sstor = await stors.query(globalThis.sessionStorage);
    },
    Cookie: async () => {
      data.cookie = await cookies.query();
    },
    lStor: async () => {
      data.lstor = await stors.query(globalThis.localStorage);
    },
    Cache: async () => {
      data.cache = await caches.query();
    },
  } as const;

  const keys = Object.keys(getter);
  for (const key of keys) {
    await runner(
      DataType[key as keyof typeof DataType],
      type,
      getter[key as keyof typeof DataType],
      hint(DataString[key as keyof typeof DataString], 1),
    );
  }

  return data;
}

async function clearData(type: number) {
  const cleaner = {
    indexedDB: async () => {
      await dbs.clear();
    },
    sStor: async () => {
      await stors.clear(globalThis.sessionStorage);
    },
    Cookie: async () => {
      await cookies.clear();
    },
    lStor: async () => {
      await stors.clear(globalThis.localStorage);
    },
    Cache: async () => {
      await caches.clear(3);
    },
  } as const;

  const keys = Object.keys(cleaner);
  for (const key of keys) {
    await runner(
      DataType[key as keyof typeof DataType],
      type,
      cleaner[key as keyof typeof DataType],
      hint(DataString[key as keyof typeof DataString], 2),
    );
  }

  alert("清理完毕");
}

GM_registerMenuCommand("查看统计数据", async () => {
  let prompts = "";
  if (typeof navigator.storage.estimate == "function") {
    const quota = await navigator.storage.estimate();
    prompts += `网站存储配额（不准确）
已用 ${String(Math.floor(quota.usage ?? 0))}
可用 ${String(Math.floor(quota.quota ?? 0))}
`;
    /* 缺乏类型
    if (quota.usageDetails) {
      prompts += `${JSON.stringify(quota.usageDetails, null, 2)}
`;
    }
    */
  }

  prompts += `选择确定清理全部
------
`;

  const data = await getData(31);

  if (data.cookie) {
    prompts += `${cookies.summary(data.cookie)}
`;
  }

  if (data.lstor) {
    prompts += `${stors.summary(DataString.lStor, data.lstor)}
`;
  }

  if (data.sstor) {
    prompts += `${stors.summary(DataString.sStor, data.sstor)}
`;
  }

  if (data.dbs) {
    prompts += `${dbs.summary(data.dbs)}
`;
  }

  if (data.cache) {
    prompts += `${caches.summary(data.cache)}
`;
  }

  if (confirm(prompts)) {
    await clearData(31);
  }
});

GM_registerMenuCommand(hint(DataString.Cookie, 3), async () => {
  let prompts = hint(DataString.Cookie, 0);
  const data = await getData(DataType.Cookie);
  if (data.cookie) {
    prompts += `${cookies.summary(data.cookie)}
`;
    for (const cookie of data.cookie.data) {
      prompts += `------
${cookies.stringify(cookie)}
`;
    }
    if (confirm(prompts)) {
      await clearData(DataType.Cookie);
    }
  }
});

GM_registerMenuCommand(hint(DataString.lStor, 3), async () => {
  let prompts = hint(DataString.lStor, 0);
  const data = await getData(DataType.lStor);
  if (data.lstor) {
    prompts += `${stors.summary(DataString.lStor, data.lstor)}
${stors.stringify(data.lstor)}`;
    if (confirm(prompts)) {
      await clearData(DataType.lStor);
    }
  }
});

GM_registerMenuCommand(hint(DataString.sStor, 3), async () => {
  let prompts = hint(DataString.sStor, 0);
  const data = await getData(DataType.sStor);
  if (data.sstor) {
    prompts += `${stors.summary(DataString.sStor, data.sstor)}
${stors.stringify(data.sstor)}`;
    if (confirm(prompts)) {
      await clearData(DataType.sStor);
    }
  }
});

GM_registerMenuCommand(hint(DataString.Cache, 3), async () => {
  let prompts = hint(DataString.Cache, 0);
  const data = await getData(DataType.Cache);
  if (data.cache) {
    prompts += `${caches.summary(data.cache)}
${caches.stringify(data.cache)}`;

    if (confirm(prompts)) {
      await clearData(DataType.Cache);
    }
  }
});

GM_registerMenuCommand(hint(DataString.indexedDB, 3), async () => {
  let prompts = hint(DataString.indexedDB, 0);
  const data = await getData(DataType.indexedDB);
  if (data.dbs) {
    prompts += `${dbs.summary(data.dbs)}
${dbs.stringify(data.dbs)}`;

    if (confirm(prompts)) {
      await clearData(DataType.indexedDB);
    }
  }
});

void gmHostMenu(
  "lemon-workerBlockDomains",
  "拦截此源 Service Worker",
  "解除拦截 Service Worker",
  () => {
    navigator.serviceWorker.register = () => {
      return Promise.reject(new Error("hello"));
    };
  },
  async () => {
    await caches.clear(3);
  },
);

window.addEventListener("load", () => {
  try {
    if (!isEmotionUsed()) initUI();
  } catch (error) {
    console.error(error);
  }
});
